<?php
/*
Plugin Name: LUTube Shortcode
Plugin URI: http://code.google.com/p/lutube-shortcode-plugin/
Description: Shortcode for embedding LUTube video. For instructions and a tool to help generate shortcodes, <a href="tools.php?page=lutube-help">see the help page</a>, or <a href="http://code.google.com/p/lutube-shortcode-plugin/">see the project page on Google Code</a>.
Author: Peter Edwards
Author URI: http://www.essl.leeds.ac.uk/for-staff/staff/edwards.html
Version: 0.2
License: GPL3

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

if ( ! class_exists("LUTubeShortcode") ):
/**
 * LUTubeShortcode class
 * Static class used to embed HTML into the post, include JavaScript, 
 * and trigger the lutube video instance on the page.
 * @version 1.2
 * @author Peter Edwards <p.l.edwards@leeds.ac.uk>
 */
class LUTubeShortcode
{
    /**
     * constructor - disallow instantiation
     */
    final private function LUTubeShortcode()	{}
	
	/**
	 * constructior (PHP5) 
	 */
	final private function __construct() {}

	/**
     * registers all actions in Wordpress API
	 */
	public static function register()
	{
    	/* add a page describing the use of the shortcode */
    	add_action('admin_menu', array('LUTubeShortcode', 'add_menus'));
    	/* add shortcode */
        add_shortcode('lutube', array('LUTubeShortcode', 'lutube_shortcode') );
        /* enqueues scripts if neccessary */
        add_action('init', array('LUTubeShortcode','lutube_shortcode_init'), 50);
        /* adds a link to the help page from the plugins page */
        add_filter('plugin_action_links', array('LUTubeShortcode', 'add_help_page_link'), 10, 2 );
	}
    
	/**
	 * enqueue jQuery and shortcode script if needed
	 */
 	function lutube_shortcode_init()
 	{
        if (!is_admin()) {
        	wp_enqueue_script('swfobject');
     		wp_register_script('lutubeshortcode', plugins_url('/js/LUTubeShortcode.js', __FILE__));
	        wp_enqueue_script('lutubeshortcode', array('jquery','swfobject'));
        }
    }
    
    /**
     * lutube shortcode callback function
     * @param array attributes of shortcode arguments
     * @return string HTML
     */
    public static function lutube_shortcode( $atts )
    {
    	/* static variable to track multiple instances on a page */
	    static $vid_id = 0;
	    
	    /* shortcode options */
	    $options = shortcode_atts( array(
	        'hash' => '',
	        'id' => '',
	        'class' => 'lutubevideo',
	        'width' => '640',
	        'height' => '360',
	        'autoplay' => '0',
	        'controls' => '1',
	        'preload' => '0',
	        'title' => 'LUTube Video',
	        'poster' => false,
	        'debug' => false,
	        'method' => ''
	    ), $atts );
	    
	    /* whether or not debugging is turned on */
	    $debug = (bool) $options["debug"];
	    
	    /* set id either manually or automatically */
	    $id = ($options["id"] == '')? 'lutubevideo-' . $vid_id++: $options["id"];
	    
	    /* get all the video parameters */
	    $src = $options["hash"];
	    $baseline_src = $src . ".m4v";
	    $theora_src = $src . ".ogv";
	    $webm_src = $src . ".webm";
	    $flashsrc = "http://lutube.leeds.ac.uk/video/" . $src;
	    
	    /* get other parameters */
	    if ($options["poster"] === false) {
	        $poster = "http://lutube.leeds.ac.uk/binary/thumb/" . $src;
	    } else {
	    	$poster = esc_attr($options["poster"]);
	    }
	    $autoplay = (bool) $options["autoplay"];
	    $controls = (bool) $options["controls"];
	    $preload = (bool) $options["preload"];
	    $width = intval($options["width"]);   
	    $height = intval($options["height"]);
	    $class = (trim($options["class"]) != "")? " " . $options["class"]: "";
	    $title = esc_attr($options["title"]);
	    
	    /* start debugging output */
        $dbg_msg = '<div id="' . $id . '-debug" class="lutube-debug"><h3>Debugging Information:</h3><p><strong>shortcode attributes</strong></p><ul>';
        foreach ($atts as $key => $val) {
        	$dbg_msg .= sprintf('<li><strong>%s</strong>: %s</li>', $key, $val);
        }
        $dbg_msg .= '</ul><p><strong>embed options</strong></p><ul>';
        foreach ($options as $key => $val) {
        	$dbg_msg .= sprintf('<li><strong>%s</strong>: %s</li>', $key, $val);
        }
        $dbg_msg .= '</ul><p><strong>Video Sources</strong><p><ul>';
        
        /* start output */
        $output = "<div class=\"lutube-video-wrap" . $class . "\" id=\"" . $id . "-container\" style=\"width:" . $width . "px;height:" . $height . "px;\">\n  <div id=\"" . $id . "\">\n";
        
        /* attribute shortcuts */
        $auto_attr = $autoplay? ' autoplay': '';
        $controls_attr = $controls? ' controls': '';
        $preload_attr = $preload? ' preload': ' preload="none"';
        $poster_attr = ' poster="' . $poster . '"';
        /* detect for iOS 3 and omit poster attribute */
        if (preg_match('/([0-9_])* like Mac OS/i', $_SERVER['HTTP_USER_AGENT'], $matches)) {
        	if ($matches[1] != "" && substr($matches[1], 0, 1) == "3") {
        		$poster_attr = '';
        	}
        }
        
        /* check existence of differently encoded videos */
        $has_baseline = self::lutube_has_file($baseline_src, $debug);
        $has_webm = self::lutube_has_file($webm_src, $debug);
        $has_theora = self::lutube_has_file($theora_src);
        
        /* Flash source with image fallback */
        $flash_output = "      <object width=\"" . $width . "\" height=\"" . $height . "\" type=\"application/x-shockwave-flash\" data=\"" . $flashsrc . "\">\n";
		$flash_output .= "        <param name=\"movie\" value=\"" . $flashsrc . "\" />\n";
		if ($autoplay) {
		    $flash_output .= "        <param name=\"flashvars\" value=\"autoplay=true\" />\n";
		    $flash_output .= "        <param name=\"autoplay\" value=\"true\" />\n";
		}
       	$flash_output .= "        <param name=\"allowfullscreen\" value=\"true\" />\n";
       	$flash_output .= "        <param name=\"allowscriptaccess\" value=\"sameDomain\" />\n";
       	$flash_output .= "        <img src=\"" . $poster . "\" width=\"" . $width . "\" height=\"" . $height . "\" alt=\"" . $title . "\" title=\"" . $title . "\" />\n";
       	$flash_output .= "      </object>\n";
        
        /* build output based on embed method */
        switch ($options["method"]) {
        	
        	case "HTML5":

        		/**
        		 * embeds the video as HTML5 with flash fallback 
        		 * from http://camendesign.com/code/video_for_everybody
        		 */
        		
        		/* output opening video tag */
                $output .= "    <video width=\"" . $width . "\" height=\"" . $height . "\" title=\"" . $title . "\" " . $poster_attr . $auto_attr . $controls_attr . $preload_attr . ">\n";
                
                /* h.264 sources - use baseline in preference to extended for maximum compatibility */
                if ($has_baseline === true) {
                    $output .= "      <source src=\"http://lutube.leeds.ac.uk/binary/" . $baseline_src . "\" type='video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\"' />\n";
                    $dbg_msg .= '<li>h.264 baseline video source found at http://lutube.leeds.ac.uk/binary/' . $baseline_src . '</li>';
                } else {
                    $output .= "      <source src=\"http://lutube.leeds.ac.uk/binary/" . $src . "\" type='video/mp4; codecs=\"avc1.64001E, mp4a.40.2\"' />\n";
        	        $msg = $has_baseline === false? "no errors": $has_baseline;
                    $dbg_msg .= '<li>h.264 baseline video source not found - using extended profile at http://lutube.leeds.ac.uk/binary/' . $src . ' - fgets returned <em>' . $msg . '</em></li>';
                }
            
                /* WebM source */
                if ($has_webm === true) {
                    $output .= "      <source src=\"http://lutube.leeds.ac.uk/binary/" . $webm_src . "\" type='video/webm; codecs=\"vp8, vorbis\"'>\n";
                    $dbg_msg .= '<li>WebM video source found at http://lutube.leeds.ac.uk/binary/' . $webm_src . '</li>';
                } else {
        	        $msg = $has_webm === false? "no errors": $has_webm;
        	        $dbg_msg .= '<li>WebM video source not found - fgets returned <em>' . $msg . '</em></li>';
                }
            
                /* Theora source */
                if ($has_theora === true) {
                    $output .= "      <source src=\"http://lutube.leeds.ac.uk/binary/" . $theora_src . "\" type='video/ogg; codecs=\"theora, vorbis\"'>\n";
                    $dbg_msg .= '<li>Theora video source found at http://lutube.leeds.ac.uk/binary/' . $theora_src . '</li>';
                } else {
        	        $msg = $has_theora === false? "no errors": $has_theora;
        	        $dbg_msg .= '<li>Theora video source not found - fgets returned <em>' . $msg . '</em></li>';
                }
                
                /* Flash source with image fallback */
                $output .= $flash_output;

       		    /* close video tag */
                $output .= "    </video>\n";
                
                break;
        	
            case "flash":
                
                /**
        		 * flash only - using code similar to that on the LUTube site
        		 */
                $output .= $flash_output;
        		       		
        		break;
                
            default:

            	/**
        		 * outputs as single video tag with src attribute set to the h.264 
        		 * (baseline if available) video. Should be supplemented by jQuery
        		 * script to replace with flash player if needed
        		 */
        	    $output .= '    <video width="' . $width . '" height="' . $height . '" title="' . $src . '"' . $poster_attr . $auto_attr . $controls_attr . $preload_attr . ' src="';
                if ($has_baseline === true) {
                    $output .= 'http://lutube.leeds.ac.uk/binary/' . $baseline_src;
                    $dbg_msg .= '<li>h.264 baseline video source found at http://lutube.leeds.ac.uk/binary/' . $baseline_src . '</li>';
                } else {
                    $output .= 'http://lutube.leeds.ac.uk/binary/' . $src;
        	        $msg = $has_baseline === false? "no errors": $has_baseline;
                    $dbg_msg .= '<li>h.264 baseline video source not found - using extended profile at http://lutube.leeds.ac.uk/binary/' . $src . ' - fgets returned <em>' . $msg . '</em></li>';
                }
                $output .= '">' . "\n";
                $output .= $flash_output;
                $output .= "    </video>\n";
                
                break;
        	
        }

        $output .= "  </div>\n</div>\n";
        $dbg_msg .= '</ul><p>Video embed HTML</strong></p><pre style="overflow:auto;background:#efefef;">' . htmlentities($output) . '</pre></div>';
        if ($debug) {
        	$output .= $dbg_msg;
        }
        return $output;
    }

    /**
     * check to see if lutube has a given file using a HEAD HTTP request
     * @param string filename
     * @return boolean
     */
    public static function lutube_has_file($filename, $debug = false)
    {
        $proxy = false;//array("host" => "www-cache.leeds.ac.uk", "port" => "3128");
    	if ($proxy) {
    		$host = $proxy["host"];
    		$port = $proxy["port"];
    	} else {
    		$host = "lutube.leeds.ac.uk";
    		$port = "80";
    	}
    	$socket = @fsockopen( $host, $port, $errno, $errstr, 2 );
        if ($socket) {
        	if ($proxy) {
                fputs($socket, "HEAD http://lutube.leeds.ac.uk/binary/" . $filename . " HTTP/1.0\r\nHost: http://lutube.leeds.ac.uk:80\r\nUser-Agent: LUTubeShortcode\r\n\r\n");
        	} else {
        		fputs($socket, "HEAD /binary/" . $filename . " HTTP/1.0\r\nHost: http://lutube.leeds.ac.uk:80\r\nUser-Agent: LUTubeShortcode\r\n\r\n");
        	}
            $http_response = fgets( $socket, 22 );
            if ( ereg("200 OK", $http_response, $regs ) ) {
                fclose( $socket );
                return true;
            }
            fclose($socket);
        } else {
        	if ($debug) {
        		return $errstr . " (" . $errno . ")";
        	}
        }
        return false;
    }

    /**
     * adds a menu item to tools
     */
    public static function add_menus()
    {
    	add_submenu_page('tools.php', 'lutube-help', 'LUTube shortcode', 'edit_posts', 'lutube-help', array('LUTubeShortcode', 'help_page') );
    }
    /**
     * prints a help page which is added to the Wordpress Tools menu
     */
    public static function help_page()
    {
    	$out = '<div class="wrap"><div id="icon-themes" class="icon32"></div><h2>Adding an LUTube video to your page or post</h2>';
    	$out .= '<p>This page explains how to add an <a href="http://lutube.leeds.ac.uk/">LUTube video</a> to your page or post using a Wordpress shortcode. This will take care of inserting the tags needed to embed the video, and include any scripts which are needed to activate it. If your page or post is going to be on a public website, <strong>the settings in LUTube must be set so the video is public</strong>, otherwise only users within the University network will be able to watch it.</p>';
    	$out .= '<h2>Using shortcodes</h2>';
    	$out .= '<p><strong>Shortcodes</strong> in Wordpress are used to simplify adding complex markup to pages to embed things like video, audio, scripts and image galleries. To use a shortcode, you type a keyword in square brackets in the content of your post/page wherever you want the object you are embedding to be. The shortcode can also hold additional information, or options, in a series of name/value pairs, e.g.</p>';
    	$out .= '<p><code>[shortcode_keyword option1="value1" option2="value2"]</code></p>';
    	$out .= '<p>To embed an LUTube video in your page, you would use the <code>lutube</code> keyword with a single option to tell the shortcode where your video is stored. LUTube uses <em>hashes</em> to identify videos, and the hash of your video can be found in the code which is given on a video page to embed the video on other sites, which looks like this:</p>';
    	$out .= '<p><code>&lt;object width="640" height="360"&gt;<br />  &lt;param name="movie" value="http://lutube.leeds.ac.uk/video/<span style="color:#69c;">9086968d503732a11b00dd78e362285a</span>" /&gt;<br />  &lt;param name="allowFullScreen" value="true" /&gt;<br />  &lt;param name="allowScriptAccess" value="sameDomain" /&gt;<br />  &lt;embed type="application/x-shockwave-flash" width="640" height="360" allowfullscreen="true" allowscriptaccess="always"<br />   src="http://lutube.leeds.ac.uk/video/<span style="color:#69c">9086968d503732a11b00dd78e362285a</span>"&gt;<br />  &lt;/embed&gt;<br />&lt;/object&gt;</code></p>';
    	$out .= '<p>The hash value for the video above is highlighted - this is the text you will need to add to your shortcode to identify the video:</p>';
    	$out .= '<p><code>[lutube hash="9086968d503732a11b00dd78e362285a"]</code></p>';
    	$out .= '<h3>Shortcode generator</h3>';
    	$out .= '<p>Paste the LUTube embed code in the box below, set optional settings, and click on the generate code button:</p>';
    	$out .= '<p><textarea id="shortcode_generator_src" cols="80" rows="6"></textarea></p>';
    	$out .= '<p><strong>Width and Height</strong> - make sure you preserve the aspect ratio of the video if you are going to change these from the defaults.</p>';
        $out .= '<p><input type="text" id="shortcode_generator_width" value="" size="3" /><label for="shortcode_generator_width">Width of player (in pixels)</label></p>';    	
        $out .= '<p><input type="text" id="shortcode_generator_height" value="" size="3" /><label for="shortcode_generator_height">Height of player (in pixels)</label></p>';
        $out .= '<p><strong>Settings</strong> - the default settings should be used in most cases</p>';
        $out .= '<p><input type="checkbox" id="shortcode_generator_controls" checked="checked" /><label for="shortcode_generator_controls">Whether to show the controls for the video in native players (currently on iOS devices only)</label></p>';	
        $out .= '<p><input type="checkbox" id="shortcode_generator_autoplay" /><label for="shortcode_generator_autoplay">Whether to start playing video as soon as the page loads (not recommended)</label></p>';	
        $out .= '<p><input type="checkbox" id="shortcode_generator_preload" /><label for="shortcode_generator_preload">Whether to preload video (not recommended)</label></p>';	
        $out .= '<p><input type="button" id="shortcode_generator_generate" class="button-primary" value="Generate shortcode" /></p>';
        $out .= '<p><code id="shortcode_generator_results"></code></p>';
        $out .= '<script type="text/javascript">jQuery(function(a){a("#shortcode_generator_generate").click(function(){var d=a("#shortcode_generator_src").val();var c="";if(a.trim(d)!==""){var b=/lutube\.leeds\.ac\.uk\/video\/([^"]*)/.exec(d);if(b&&b.length){c+=\'[lutube hash="\'+b[1]+\'"\';if(a("#shortcode_generator_width").val()!=""){c+=\' width="\'+parseInt(a("#shortcode_generator_width").val())+\'"\'}if(a("#shortcode_generator_height").val()!=""){c+=\' height="\'+parseInt(a("#shortcode_generator_height").val())+\'"\'}if(!a("#shortcode_generator_controls:checked").length){c+=\' controls="0"\'}if(a("#shortcode_generator_autoplay:checked").length){c+=\' autoplay="1"\'}if(a("#shortcode_generator_preload:checked").length){c+=\' preload="1"\'}c+="]";a("#shortcode_generator_results").text(c)}}})});</script>';
        $out .= '<h3>Available options</h3>';
    	$out .= '<dl><dt><strong>hash</strong></dt><dd><em><strong>required</strong></em> The hash of the video on LUTube (see above)</dd>';
    	$out .= '<dl><dt><strong>class</strong></dt><dd><em>optional (default "lutubevideo")</em> An extra CSS calss to apply to the video container</dd>';
    	$out .= '<dt><strong>width</strong></dt><dd><em>optional (default 640)</em> The width of the video in pixels</dd>';
    	$out .= '<dt><strong>height</strong></dt><dd><em>optional (default 360)</em> The height of the video in pixels</dd>';
    	$out .= '<dt><strong>preload</strong></dt><dd><em>optional (default 0 - false)</em> Whether the browser should start downloading the video when the page loads</dd>';
    	$out .= '<dt><strong>autoplay</strong></dt><dd><em>optional (default 0 - false)</em> Whether the video should start to play as soon as it can (this has precedence over the preload setting if set)</dd>';
    	$out .= '<dt><strong>controls</strong></dt><dd><em>optional (default 1 - true)</em> Whether to show controls on the video to enable puasing, volume control and seeking (this is browser dependent)</dd>';
    	$out .= '<dt><strong>poster</strong></dt><dd><em>optional (default 0 -false)</em> The URL of an image to be used as the "poster" for the video (the default poster from LUTube is used by default).</dd></dl>';
    	$out .= "<div>\n";
    	print($out);
    }
    
    /**
     * adds a link to the help page from the plugins listing page
     * called using the plugin_action_links filter
     */
    function add_help_page_link($links, $file)
    {
        if ($file == plugin_basename(__FILE__)) {
            $help_page_link = '<a href="tools.php?page=lutube-help">Help</a>';
            array_unshift($links, $help_page_link);
        }
        return $links;
    }

}
LUTubeShortcode::register();
endif;

$lutube_admin_script = <<<EOF
jQuery(function($){
	$('#shortcode_generator_generate').click(function(){
		var text = $('#shortcode_generator_src').val();
		var sc = "";
		if ($.trim(text) !== '') {
			var match = /lutube\.leeds\.ac\.uk\/video\/([^"]*)/.exec(text);
			if (match && match.length) {
				sc += '[lutube hash="'+match[1]+'"';
				if ($('#shortcode_generator_width').val() != '') {
					sc += ' width="'+parseInt($('#shortcode_generator_width').val())+'"';
				}
				if ($('#shortcode_generator_height').val() != '') {
					sc += ' height="'+parseInt($('#shortcode_generator_height').val())+'"';
				}
				if (!$('#shortcode_generator_controls:checked').length) {
					sc += ' controls="0"';
				}
				if ($('#shortcode_generator_autoplay:checked').length) {
					sc += ' autoplay="1"';
				}
				if ($('#shortcode_generator_preload:checked').length) {
					sc += ' preload="1"';
				}
				sc += ']';
				$('#shortcode_generator_results').text(sc);
			}
		}
	});
});
EOF;
?>